package com.module.antiFake.dao;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;

import base.dao.GenericHibernateDao;
import base.util.Page;

import com.module.antiFake.vo.AntiFakeOrgConfig;
import com.module.antiFake.vo.AntiFakeScanHistory;
import com.module.antiFake.vo.AntiFakeScanTimes;
import com.module.antiFake.vo.AntiFakeWarn;


public class AntiFakeWarnDao extends GenericHibernateDao<AntiFakeWarn, Long> {
	private Log logger = LogFactory.getLog(AntiFakeWarnDao.class);
	private static AntiFakeWarnDao dao;
	private AntiFakeOrgConfigDao orgConfigDao = AntiFakeOrgConfigDao
			.getInstance();
	private AntiFakeScanTimesDao scanTimesDao = AntiFakeScanTimesDao
			.getInstance();
	private AntiFakeScanHistoryDao scanHistoryDao = AntiFakeScanHistoryDao
			.getInstance();
	private AntiFakeLBSDao antiFakeLBSDao = AntiFakeLBSDao.getInstance();

	public AntiFakeWarnDao() {
		super();
	}

	public synchronized static AntiFakeWarnDao getInstance() {
		if (dao == null) {
			dao = new AntiFakeWarnDao();
		}
		return dao;
	}
	/**
	 * 预警信息列表
	 * @param session
	 * @param antiFakeWarn
	 * @param page
	 */
	@SuppressWarnings("unchecked")
	public void getList(Session session, AntiFakeWarn antiFakeWarn, Page page) {
		String whereStr = "";
		String hql = "FROM AntiFakeWarn warn ";
		String hqlCount = "SELECT count(*) FROM AntiFakeWarn warn ";
		String split = " WHERE ";
		if (StringUtils.isNotBlank(antiFakeWarn.getCodeInfo())) {
			whereStr += split + " warn.codeInfo like '%"
					+ antiFakeWarn.getCodeInfo() + "%' ";
			split = " AND ";
		}
		if (StringUtils.isNotBlank(antiFakeWarn.getOrgid())) {
			whereStr += split + " warn.orgid='" + antiFakeWarn.getOrgid()
					+ "' ";
			split = " AND ";
		}
		// -2为全部;
		if (antiFakeWarn.getProcessState() != null
				&& !antiFakeWarn.getProcessState().equals(new Short("-2"))) {
			whereStr += split + " warn.processState='"
					+ antiFakeWarn.getProcessState() + "' ";
			split = " AND ";
		}
		// 0为全部
		if (antiFakeWarn.getType() != null
				&& !antiFakeWarn.getType().equals(new Short("0"))) {
			whereStr += split + "warn.type='" + antiFakeWarn.getType() + "'";
			split = "AND";
		}
		Query query = session.createQuery(hql + whereStr
				+ " ORDER BY warn.createtime DESC");
		query.setFirstResult(page.getStart()).setMaxResults(page.getLimit());

		page.setTotal((long) ((Long) session.createQuery(hqlCount + whereStr)
				.uniqueResult()).intValue());
		page.setRows(query.list());
	}

	public long countUntreateNumByOrgId(Session session, String orgid)
			throws Exception {
		long result = 0;
		try {
			String hqlCount = "SELECT count(*) FROM AntiFakeWarn warn where warn.orgid='"
					+ orgid
					+ "' AND warn.processState="
					+ AntiFakeWarn.PROCESS_STATE_ORG;
			result = (long) ((Long) session.createQuery(hqlCount)
					.uniqueResult()).intValue();
		} catch (Exception e) {
			throw e;
		}
		return result;
	}

	/**
	 * 企业预警扫描 非事务运行;
	 */
	public void scanTimesWarn(Session session) {
		logger.info("start scan antifakeScanTimes record...");
		doScanScanTimes(session);
	}

	private void doScanScanTimes(Session session) {
		// 取出企业防伪数据配置;
		List<AntiFakeOrgConfig> orgConfigList = orgConfigDao.findBySQL(session,
				"From AntiFakeOrgConfig conf");
		Map<String, AntiFakeOrgConfig> orgConfigMap = new HashMap<String, AntiFakeOrgConfig>();
		int minFirstTimes = AntiFakeOrgConfig.DEF_FIRST_CODE_TIMES;
		int minSecondTimes = AntiFakeOrgConfig.DEF_SECOND_CODE_TIMES;
		int minTransshipmentTimes = AntiFakeOrgConfig.DEF_TRANSSHIPMENT_TIMES;
		// 循环找出企业设置中第一，二层码及窜货次数的最小设置值;
		for (AntiFakeOrgConfig config : orgConfigList) {
			if (config.getFirstCodeTimes() != null
					&& config.getFirstCodeTimes().intValue() < minFirstTimes) {
				minFirstTimes = config.getFirstCodeTimes().intValue();
			}
			if (config.getSecondCodeTimes() != null
					&& config.getSecondCodeTimes().intValue() < minSecondTimes) {
				minSecondTimes = config.getSecondCodeTimes().intValue();
			}
			if (config.getTranTimes() != null
					&& config.getTranTimes().intValue() < minSecondTimes) {
				minTransshipmentTimes = config.getTranTimes().intValue();
			}
			orgConfigMap.put(config.getOrgid(), config);
		}
		// 扫描第一层码并符合条件的，记录到防伪预警中;
		scanFirstCodeAndSaveWarn(session, orgConfigMap, minFirstTimes);
		// 扫描第二层码并符合条件的，记录到防伪预警中;
		scanSecondCodeAndSaveWarn(session, orgConfigMap, minSecondTimes);
		// 扫描符合窜货条件的批次，并记录在防伪预警表中;
		scanTransshipmentAndSaveWarn(session, orgConfigMap,
				minTransshipmentTimes);

	}

	/**
	 * 扫描第二层码并符合条件的，记录到防伪预警中;
	 * @param session
	 * @param orgConfigMap
	 * @param minFirstTimes
	 */
	private void scanSecondCodeAndSaveWarn(Session session,
			Map<String, AntiFakeOrgConfig> orgConfigMap, int minSecondTimes) {
		scanCodeAndSaveWarn(session, orgConfigMap, minSecondTimes, 2);
	}

	/**
	 * 扫描第一层码并符合条件的，记录到防伪预警中;
	 * 
	 * @param session
	 * @param orgConfigMap
	 * @param minFirstTimes
	 */
	private void scanFirstCodeAndSaveWarn(Session session,
			Map<String, AntiFakeOrgConfig> orgConfigMap, int minFirstTimes) {
		int layerNum = 1;
		scanCodeAndSaveWarn(session, orgConfigMap, minFirstTimes, layerNum);
	}

	/**
	 * 扫描窜货记录;
	 * 
	 * @param session
	 * @param orgConfigMap
	 * @param minTransshipmentTimes
	 */
	private void scanTransshipmentAndSaveWarn(Session session,
			Map<String, AntiFakeOrgConfig> orgConfigMap,
			int minTransshipmentTimes) {
		String scanHql = " FROM AntiFakeScanHistory history where (history.lbsId!=0 and history.lbsId!=null "
				+ "and history.salesAreaId!=0 and history.salesAreaId!=null) and history.salesAreaId!=history.lbsId"
				+ " and history.batchNo not in (SELECT warn.batchNo FROM AntiFakeWarn warn where warn.type ="
				+ AntiFakeWarn.TYPE_TRANSSHIPMENT_WARN
				+ " and warn.processState!="
				+ AntiFakeWarn.PROCESS_STATE_ORG
				+ ") group by history.productId"
				+ " having count(batchNo)>="
				+ minTransshipmentTimes;
		List<AntiFakeScanHistory> scanHistoryList = scanHistoryDao.findBySQL(
				session, scanHql);
		for (AntiFakeScanHistory history : scanHistoryList) {
			// System.out.println("show batchNo: "+history.getBatchNo()+"\t prodictId:"+history.getProductId());
			// System.out.println("show productName: "+history.getProductName());
			AntiFakeWarn antiFakeWarn = new AntiFakeWarn();
			antiFakeWarn.setProductId(history.getProductId());
			antiFakeWarn.setProductName(history.getProductName());
			antiFakeWarn.setRollNum(history.getRollNum());
			antiFakeWarn.setOrgid(history.getOrgid());
			antiFakeWarn.setOrgName(history.getOrgName());
			antiFakeWarn.setProcessState(AntiFakeWarn.PROCESS_STATE_ORG);
//			antiFakeWarn.setCreatetime(new Date());
			antiFakeWarn.setCreatetime(history.getCreatetime());
			antiFakeWarn.setCodeInfo(history.getCodeInfo());
			antiFakeWarn.setBatchNo(history.getBatchNo());
			antiFakeWarn.setType(AntiFakeWarn.TYPE_TRANSSHIPMENT_WARN);
			antiFakeWarn.setTimes(scanHistoryDao.countByBatchNo(session,
					history.getBatchNo()).intValue());
			antiFakeWarn.setSalesAddr(antiFakeLBSDao.getAddressById(session,
					history.getSalesAreaId()));
			saveOrUpdate(session, antiFakeWarn);
		}
		session.flush();
	}

	private void scanCodeAndSaveWarn(Session session,
			Map<String, AntiFakeOrgConfig> orgConfigMap, int minFirstTimes,
			int layerNum) {
		String scanHql = "FROM AntiFakeScanTimes scanTime WHERE scanTime.times>="
				+ minFirstTimes
				+ " AND scanTime.layerNum="
				+ layerNum
				+ " AND scanTime.codeInfo NOT IN "
				+ "(SELECT warn.codeInfo FROM AntiFakeWarn warn WHERE (warn.type ="
				+ AntiFakeWarn.TYPE_FIRST_CODE_WARN
				+ " or warn.type="
				+ AntiFakeWarn.TYPE_SECOND_CODE_WARN
				+ ") and warn.processState!="
				+ AntiFakeWarn.PROCESS_STATE_ORG
				+ ")";
		List<AntiFakeScanTimes> scanTimesList = scanTimesDao.findBySQL(session,
				scanHql);
		int idx = 0;
		for (AntiFakeScanTimes scanTime : scanTimesList) {
			AntiFakeWarn warn = getWarnRecordFrom(session, scanTime,
					orgConfigMap, layerNum);
			if (warn != null) {
				if (warn.getId() == null
						|| (warn.getId() != null && scanTime.getTimes() != null
								&& warn.getTimes() != null && scanTime
								.getTimes().intValue() != warn.getTimes()
								.intValue())) {
					logger.info("save codeInfo:" + warn.getCodeInfo());
					saveOrUpdate(session, warn);
					if (++idx % 20 == 0) {
						session.flush();
						session.clear();
					}
				}
			}
		}
	}

	/**
	 * 从扫描记录中获取预警记录;如果当前扫描记录不符合规则，则返回null;
	 * @param scanTime
	 * @param orgConfigMap
	 * @return
	 */
	private AntiFakeWarn getWarnRecordFrom(Session session,
			AntiFakeScanTimes scanTime,
			Map<String, AntiFakeOrgConfig> orgConfigMap, int layerNum) {
		AntiFakeWarn result = null;
		int minWarnTimes = AntiFakeOrgConfig.DEF_FIRST_CODE_TIMES;

		if (layerNum == 2) {
			minWarnTimes = AntiFakeOrgConfig.DEF_SECOND_CODE_TIMES;
		}
		// 查出当前企业最小预警;
		if (orgConfigMap.containsKey(scanTime.getOrgid())) {
			AntiFakeOrgConfig config = orgConfigMap.get(scanTime.getOrgid());
			minWarnTimes = config.getFirstCodeTimes();
			if (layerNum == 2) {
				minWarnTimes = config.getSecondCodeTimes();
			}
		}

		if (scanTime.getTimes().intValue() >= minWarnTimes) {
			result = findUniqueObjectBySQL(
					session,
					"FROM AntiFakeWarn warn WHERE warn.codeInfo='"
							+ scanTime.getCodeInfo()
							+ "' AND (warn.type=1 or warn.type=2)");
			// 新记录;
			if (result == null) {
				result = AntiFakeWarn.copyFromScanTimes(scanTime);
			}
			// 旧记录;
			else {
				result.setTimes(scanTime.getTimes());
				result.setCreatetime(scanTime.getUpdatetime());
			}
		}
		return result;
	}

	public AntiFakeWarn getWarnById(Session session, Long id) {
		AntiFakeWarn warn = get(session, id);
		AntiFakeScanTimes times = scanTimesDao.getUniqueByProperty(session,
				"codeInfo", warn.getCodeInfo());
		if (times != null) {
			warn.setTimes(times.getTimes());
		}
		return warn;
	}
	/**
	 * 查询下一条预警信息
	 * @param session
	 * @param id
	 * @param orgId
	 * @return
	 */
	public AntiFakeWarn getNextAntiFakeWarn(Session session, Long id,
			String orgId) {
		AntiFakeWarn bean = new AntiFakeWarn();
		List<AntiFakeWarn> list = this.findBySQL(session,
				"from AntiFakeWarn where orgid='" + orgId + "'and id<" + id
						+ " and processState ="
						+ AntiFakeWarn.PROCESS_STATE_ORG + " ORDER BY id DESC");
		if (!list.isEmpty() && list.size() > 0) {
			bean = list.get(0);
			AntiFakeScanTimes times = scanTimesDao.getUniqueByProperty(session,
					"codeInfo", bean.getCodeInfo());
			if (times != null) {
				bean.setTimes(times.getTimes());
			}
		}

		return bean;
	}
}
